package com.ruoyi.web.controller.wx;

import com.ruoyi.business.domain.*;
import com.ruoyi.business.domain.dto.CalenderDto;
import com.ruoyi.business.domain.dto.StudyPlanDto;
import com.ruoyi.business.domain.dto.StudyRecordDto;
import com.ruoyi.business.service.*;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.ErrorCode;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.wechat.pay.java.core.http.UrlEncoder;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <pre>
 *
 * </pre>
 *
 * @author zhangli
 * @since 2023/10/27
 */
@Slf4j
@Anonymous
@RestController
@RequestMapping("/wx")
public class WxAuthController {

    @Autowired
    private WxMpService wxMpService;

    @Autowired
    private BizBindDataService bizBindDataService;

    @Autowired
    private BizPlanDataService bizPlanDataService;

    @Autowired
    private BizScoreDataService bizScoreDataService;
    @Autowired
    private BizUserDataService bizUserDataService;

    @Autowired
    private BizLightDataService bizLightDataService;

    private final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

    @CrossOrigin
    @RequestMapping("/getUserInfo")
    public AjaxResult login(@RequestParam("code") String code) throws WxErrorException {

        WxOAuth2AccessToken accessToken = wxMpService
                .getOAuth2Service()
                .getAccessToken(code);

        WxOAuth2UserInfo userInfo;
        userInfo = new WxOAuth2UserInfo();
        userInfo.setOpenid(accessToken.getOpenId());

        if (StringUtils.isEmpty(userInfo.getOpenid())) {
            return AjaxResult.error(ErrorCode.WX_AUTH_ERROR);
        }

        BizBind user = bizBindDataService.getById(userInfo.getOpenid());
        if (user == null) {
            user = new BizBind();
            user.setOpenId(userInfo.getOpenid());

            bizBindDataService.save(user);
        }

        return AjaxResult.success(user);
    }

    @CrossOrigin
    @GetMapping("/authorize/code")
    public void authorize(@RequestParam Map<String, Object> params, HttpServletRequest request, HttpServletResponse response) {
        if (!params.containsKey("url")) {
            return;
        }

        String url = request.getRequestURL().toString();
        url = url.replace("http", "https");

        if (params.containsKey("code")) {
            String callBack = (String) params.remove("url");

            try {
                response.sendRedirect(callBack + "?" + formatParam(params));
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        } else {
            String callBack = url + "?" + formatParam(params);
            String authUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx474d6f098e72e156&redirect_uri=" +
                    UrlEncoder.urlEncode(callBack) + "&response_type=code&scope=snsapi_base&state=#wechat_redirect";
            try {
                response.sendRedirect(authUrl);
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }
    }

    private String formatParam(Map<String, Object> params) {
        List<String> paramList = new ArrayList<>();
        params.entrySet().forEach(entry -> paramList.add(entry.getKey() + "=" + entry.getValue()));

        return paramList.stream().collect(Collectors.joining("&"));
    }

    @CrossOrigin
    @RequestMapping("/user/bind")
    public AjaxResult userBind(@RequestParam("openId") String openId, @RequestParam("name") String name, @RequestParam("number") String number) throws WxErrorException {

        BizBind user = bizBindDataService.getById(openId);

        if (user == null) {
            return AjaxResult.error(ErrorCode.USER_NOT_EXIST);
        }

        List<BizUser> bizUserList = bizUserDataService.getByUserNumber(number);
        if (bizUserList.isEmpty()) {
            return AjaxResult.error(ErrorCode.USER_NUMBER_ERROR);
        }

        if (!bizUserList.get(0).getUserName().equals(name)) {
            return AjaxResult.error(ErrorCode.USER_NAME_ERROR);
        }

        user.setUserName(name);
        user.setUserNumber(number);
        bizBindDataService.save(user);

        return AjaxResult.success(user);
    }

    @CrossOrigin
    @RequestMapping("/study/plan")
    public AjaxResult studyPlan(@RequestParam("openId") String openId, @RequestParam(value = "weekNum", defaultValue = "0") int weekNum,@RequestParam(value = "className",defaultValue = "") String className) throws WxErrorException {

        BizBind bizBind = bizBindDataService.getById(openId);
        if (bizBind == null) {
            return AjaxResult.error(ErrorCode.USER_NOT_EXIST);
        }

        if (StringUtils.isEmpty(bizBind.getUserNumber())) {
            return AjaxResult.error(ErrorCode.NOT_BIND);
        }

        List<String> classNames = bizUserDataService.getClassNames(bizBind.getUserNumber());
        if(StringUtils.isEmpty(className)){
            className = classNames.get(0);
        }
        BizPlan bizPlan = bizPlanDataService.getByWeekNum(weekNum, className);

        if (bizPlan != null) {

            StudyPlanDto studyPlanDto = new StudyPlanDto();

            studyPlanDto.setWeekNum(bizPlan.getWeekNum());
            studyPlanDto.setCourseProject(bizPlan.getCourseProject());
            studyPlanDto.setMajorStage(bizPlan.getMajorStage());
            studyPlanDto.setWeekEnd(bizPlan.getWeekEnd());
            studyPlanDto.setWeekStart(bizPlan.getWeekStart());
            studyPlanDto.setMinorStage(bizPlan.getMinorStage());
            studyPlanDto.setClassName(bizPlan.getClassName());
            studyPlanDto.setTotalWeekNum(bizPlanDataService.getMaxWeekNum());
            studyPlanDto.setClassNameList(classNames);


            StudyPlanDto.DayPlanDto dayPlanDto1 = new StudyPlanDto.DayPlanDto();
            dayPlanDto1.setTitle("功课1");
            dayPlanDto1.setPlanInfo(bizPlan.getCourse1());
            studyPlanDto.getDayPlan().add(dayPlanDto1);

            StudyPlanDto.DayPlanDto dayPlanDto2 = new StudyPlanDto.DayPlanDto();
            dayPlanDto2.setTitle("功课2");
            dayPlanDto2.setPlanInfo(bizPlan.getCourse2());
            studyPlanDto.getDayPlan().add(dayPlanDto2);

            StudyPlanDto.DayPlanDto dayPlanDto3 = new StudyPlanDto.DayPlanDto();
            dayPlanDto3.setTitle("2000步任务目标");
            dayPlanDto3.setPlanInfo(String.valueOf(bizPlan.getTask2000b()));
            studyPlanDto.getDayPlan().add(dayPlanDto3);

            StudyPlanDto.DayPlanDto dayPlanDto4 = new StudyPlanDto.DayPlanDto();
            dayPlanDto4.setTitle("200呼任务目标");
            dayPlanDto4.setPlanInfo(String.valueOf(bizPlan.getTask200h()));
            studyPlanDto.getDayPlan().add(dayPlanDto4);

            StudyPlanDto.DayPlanDto dayPlanDto5 = new StudyPlanDto.DayPlanDto();
            dayPlanDto5.setTitle("实修分享打卡任务目标");
            dayPlanDto5.setPlanInfo(String.valueOf(bizPlan.getTaskPractice()));
            studyPlanDto.getDayPlan().add(dayPlanDto5);

            StudyPlanDto.DayPlanDto dayPlanDto6 = new StudyPlanDto.DayPlanDto();
            dayPlanDto6.setTitle("实习心得打卡任务目标");
            dayPlanDto6.setPlanInfo(String.valueOf(bizPlan.getTaskListen()));
            studyPlanDto.getDayPlan().add(dayPlanDto6);

            StudyPlanDto.DayPlanDto dayPlanDto7 = new StudyPlanDto.DayPlanDto();
            dayPlanDto7.setTitle("组学打卡任务目标");
            dayPlanDto7.setPlanInfo(String.valueOf(bizPlan.getTaskDiscuss()));
            studyPlanDto.getDayPlan().add(dayPlanDto7);

            StudyPlanDto.DayPlanDto dayPlanDto8 = new StudyPlanDto.DayPlanDto();
            dayPlanDto8.setTitle("段总结打卡任务目标");
            dayPlanDto8.setPlanInfo(String.valueOf(bizPlan.getTaskSummary()));
            studyPlanDto.getDayPlan().add(dayPlanDto8);

            return AjaxResult.success(studyPlanDto);
        }else{
            return AjaxResult.error(ErrorCode.WEEK_ERROR);
        }


    }

    @CrossOrigin
    @RequestMapping("/study/record")
    public AjaxResult studyRecord(@RequestParam("openId") String openId,@RequestParam(value = "className",defaultValue = "") String className) throws WxErrorException {
        BizBind bizBind = bizBindDataService.getById(openId);
        if (bizBind == null) {
            return AjaxResult.error(ErrorCode.USER_NOT_EXIST);
        }

        if (StringUtils.isEmpty(bizBind.getUserNumber())) {
            return AjaxResult.error(ErrorCode.NOT_BIND);
        }

        List<String> classNames = bizUserDataService.getClassNames(bizBind.getUserNumber());

        if(StringUtils.isEmpty(className)){
            className = classNames.get(0);
        }

        BizUser user = bizUserDataService.getUser(bizBind.getUserNumber(), className);

        StudyRecordDto  studyRecordDto = new StudyRecordDto();
        studyRecordDto.setClassName(className);
        studyRecordDto.setClassNameList(classNames);
        studyRecordDto.setUserName(bizBind.getUserName());
        studyRecordDto.setUserNumber(bizBind.getUserNumber());
        studyRecordDto.setCourseProject(user.getCourseProject());
        studyRecordDto.setJoinTime(user.getJoinTime());

        List<BizScore> bizScoreList = bizScoreDataService.getAllByUserNumber(bizBind.getUserNumber(), className);

        double totalScore = 0;
        double maxScore = bizPlanDataService.getBaseScore(className);
        Map<Long,Date> totalDate = new HashMap<>();
        for (BizScore bizScore : bizScoreList) {
            totalDate.put(bizScore.getCheckinDate().getTime(),bizScore.getCheckinDate());
            if(bizScore.getTask().equals("2000步")) {
                studyRecordDto.setTask2000b(studyRecordDto.getTask2000b()+1);
            }
            else if(bizScore.getTask().equals("200呼")) {
                studyRecordDto.setTask200h(studyRecordDto.getTask200h()+1);
              //  maxScore += 0.1786;
            }
            else if(bizScore.getTask().equals("组学")) {
                studyRecordDto.setTaskDiscuss(studyRecordDto.getTaskDiscuss()+1);
              //  maxScore += 3;
            }
            else if(bizScore.getTask().equals("学习心得")) {
                studyRecordDto.setTaskListen(studyRecordDto.getTaskListen()+1);
              //  maxScore += 0.2692;
            }
            else if(bizScore.getTask().equals("实修分享")) {
                studyRecordDto.setTaskPractice(studyRecordDto.getTaskPractice()+1);
               // maxScore += 0.4444;
            }
            else if(bizScore.getTask().equals("段总结")) {
                studyRecordDto.setTaskLevelNum(studyRecordDto.getTaskLevelNum()+1);
                // maxScore += 0.4444;
            }
            totalScore += bizScore.getTaskScore();
        }

        studyRecordDto.setStudyDay(totalDate.size());
        double studyLevel = bizScoreDataService.getStudyLevel(totalScore) * 100d / bizScoreDataService.getTotalPerson();
        studyRecordDto.setStudyLevel(Double.parseDouble(String.format("%.2f", studyLevel)));
        studyRecordDto.setStudyScore(Double.parseDouble(String.format("%.2f", totalScore)));
        studyRecordDto.setScoreRate(Double.parseDouble(String.format("%.3f", totalScore/maxScore)));
        studyRecordDto.setComment(user.getComment());
        List<String> honourList = new ArrayList<>();
        if(StringUtils.isNotEmpty(user.getHonour())) {
            honourList = Arrays.asList(user.getHonour().split(","));
        }
        studyRecordDto.setHonourList(honourList);

        return AjaxResult.success(studyRecordDto);
    }

    @CrossOrigin
    @RequestMapping("/study/calendar")
    public AjaxResult studyCalendar(@RequestParam("openId") String openId,@RequestParam(value = "className",defaultValue = "") String className,@RequestParam("startDate") String startDate,@RequestParam("endDate") String endDate) throws WxErrorException, ParseException {
        BizBind bizBind = bizBindDataService.getById(openId);
        if (bizBind == null) {
            return AjaxResult.error(ErrorCode.USER_NOT_EXIST);
        }

        if (StringUtils.isEmpty(bizBind.getUserNumber())) {
            return AjaxResult.error(ErrorCode.NOT_BIND);
        }

        List<String> classNames = bizUserDataService.getClassNames(bizBind.getUserNumber());

        if(StringUtils.isEmpty(className)){
            className = classNames.get(0);
        }

        Date start = simpleDateFormat.parse(startDate);
        Date end = simpleDateFormat.parse(endDate);

        List<BizScore> bizScoreList = bizScoreDataService.getAllByUserNumber(bizBind.getUserNumber(), className, start, end);

        Map<String,List<CalenderDto>> scoreMap = new HashMap<>();
        bizScoreList.forEach(score->{
            String date = simpleDateFormat.format(score.getCheckinDate());
            if(!scoreMap.containsKey(date)) {
                scoreMap.put(date,new ArrayList<>());
            }
            CalenderDto dto = new CalenderDto();
            dto.setTask(score.getTask());
            if(score.getCheckinDate().getTime() != score.getSourcetimeDay().getTime()) {
                dto.setDate(simpleDateFormat.format(score.getSourcetimeDay()));
            }
            scoreMap.get(date).add(dto);
        });


        return AjaxResult.success(scoreMap);
    }


    @CrossOrigin
    @RequestMapping("/light/plan")
    public AjaxResult lightPlan(@RequestParam("openId") String openId)  {
        BizBind bizBind = bizBindDataService.getById(openId);
        if (bizBind == null) {
            return AjaxResult.error(ErrorCode.USER_NOT_EXIST);
        }

        if (StringUtils.isEmpty(bizBind.getUserNumber())) {
            return AjaxResult.error(ErrorCode.NOT_BIND);
        }


        List<BizLight> bizLights = bizLightDataService.getAllByUserNumber(bizBind.getUserNumber());

        Map<String,Object> lightMap = new HashMap<>();
        List<BizLight> fromList = new ArrayList<>();
        List<BizLight> toList = new ArrayList<>();
        lightMap.put("from",fromList);
        lightMap.put("to",toList);
        lightMap.put("total",bizLightDataService.getTotalPerson());
        bizLights.forEach(light->{
            if(light.getLevel().equals("1") && light.getFromNumber().equals(bizBind.getUserNumber())) {
                fromList.add(light);
            }else if(light.getToNumber().equals(bizBind.getUserNumber())) {
                toList.add(light);
            }
        });


        return AjaxResult.success(lightMap);
    }

    @CrossOrigin
    @RequestMapping("/light/detail")
    public AjaxResult lightDetail(@RequestParam("id") int id)  {

        BizLight bizLight = bizLightDataService.getById(id);

        List<BizLight> bizLights = bizLightDataService.getAllByLightPulse(bizLight.getLightPulse());

        Map<String,List<BizLight>> lightMap = new HashMap<>();

        bizLights.forEach(light-> {
            if(!lightMap.containsKey(light.getLevel())) {
                lightMap.put(light.getLevel(),new ArrayList<>());
            }
            lightMap.get(light.getLevel()).add(light);
        });

        return AjaxResult.success(lightMap);
    }

}
